/**
 * 报表设计公司(2011)
 */
package net.abbp.report.view;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;

import net.abbp.report.model.Cell;
import net.abbp.report.model.ReportModel;
import net.abbp.report.model.cell.style.Style;
import net.abbp.report.view.grid.DynamicScrollBar;
import net.abbp.report.view.grid.Grid;
import net.abbp.report.view.grid.GridColumnHeader;
import net.abbp.report.view.grid.GridCornor;
import net.abbp.report.view.grid.GridRowHeader;
import net.abbp.report.view.layout.WorkSheetLayout;

import com.reportgear.report.view.grid.selection.GridSelection;
import com.reportgear.report.view.grid.selection.Selection;
import com.reportgear.report.view.grid.util.PaintUtils;

/**
 * Cell报表设计与显示面板
 * 
 * @version 1.0 2011-3-14
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 */
public class GridView extends JPanel implements PropertyChangeListener {
    private static final long serialVersionUID = 5704053503201755342L;
    /**
     * 属性-模型
     */
    public static final String PROPERTY_MODEL = "Model";
    // 报表模型
    private ReportModel reportModel;
    // 表格选择模型
    private GridSelection gridSelection;
    // 网格列头可见性
    private boolean columnHeaderVisible = true;
    // 网格行头可见性
    private boolean rowHeaderVisible = true;
    // 网格
    private Grid grid;
    // 网格行头
    private GridRowHeader gridRowHeader;
    // 网格列头
    private GridColumnHeader gridColumnHeader;
    // 左上角
    private GridCornor gridCorner;
    // 垂直滚动条
    private DynamicScrollBar verScrollBar;
    // 水平滚动条
    private DynamicScrollBar horScrollBar;

    // 水平开始值，起始列index，0 开始,列滚动条计算
    private int horiBeginValue = 0;
    // 水平值范围，显示列数,列头计算
    private int horiValueExtend = 30;
    // 垂直开始值，起始行index，0 开始，行滚动条计算
    private int vertBeginValue = 0;
    // 垂直开始值范围，显示行数，行头计算
    private int vertValueExtend = 30;

    /**
     * 显示实际行列
     */
    private boolean showActualColumnRow = true;

    // 列总数
    public GridView(ReportModel model) {
        this.setReportModel(model);

        this.initComponents();

        this.initParameters();
    }

    /**
     * 初始化参数
     */
    private void initParameters() {
    }

    // 初始化视图
    private void initComponents() {
        this.setLayout(new WorkSheetLayout());
        this.gridSelection = new GridSelection();

        this.grid = new Grid(this);
        this.gridColumnHeader = new GridColumnHeader(this);
        this.gridRowHeader = new GridRowHeader(this);
        this.gridCorner = new GridCornor(this);
        this.verScrollBar = new DynamicScrollBar(JScrollBar.VERTICAL, this);
        this.horScrollBar = new DynamicScrollBar(JScrollBar.HORIZONTAL, this);

        this.add(WorkSheetLayout.GRID_CORNOR, this.gridCorner);
        this.add(WorkSheetLayout.VER_SCROLLBAR, this.verScrollBar);
        this.add(WorkSheetLayout.HOR_SCROLLBAR, this.horScrollBar);
        this.add(WorkSheetLayout.GRID_COLUMN_HEADER, this.gridColumnHeader);
        this.add(WorkSheetLayout.GRID_ROW_HEADER, this.gridRowHeader);
        this.add(WorkSheetLayout.GRID, this.grid);

        this.addPropertyChangeListener(PROPERTY_MODEL, this.grid);
        this.addPropertyChangeListener(PROPERTY_MODEL, this.gridColumnHeader);
        this.addPropertyChangeListener(PROPERTY_MODEL, this.gridRowHeader);
        this.addPropertyChangeListener(PROPERTY_MODEL, this.gridCorner);
    }

    /**
     * 获取工作簿对应的模型
     * 
     * @return 报表模型
     */
    public ReportModel getReportModel() {
        return this.reportModel;
    }

    /**
     * 设置报表模型
     * 
     * @param reportModel
     *            报表模型
     */
    public void setReportModel(ReportModel reportModel) {
        this.firePropertyChange(PROPERTY_MODEL, this.reportModel, reportModel);

        if (this.reportModel != null) {
            this.reportModel.removePropertyChangeListener(this);
        }

        this.reportModel = reportModel;
        this.reportModel.addPropertyChangeListener(this);
    }

    /**
     * 停止编辑
     */
    public void stopEditing() {
        this.grid.stopEditing();
    }

    /**
     * 设置是否显示网格线
     * 
     * @param showGridLine
     *            是否显示网格线
     */
    public void setShowGridLine(boolean showGridLine) {
        this.grid.setShowGridLine(showGridLine);
    }

    /**
     * @return 是否显示网格线
     */
    public boolean isShowGridLines() {
        return this.grid.isShowGridLine();
    }

    /**
     * 数据改变
     */
    public void fireReportDataChanged() {
        // logger.info("fireReportDataChanged");
    }

    /**
     * 选择集改变
     */
    public void fireGridSelectionChanged() {
        // logger.info("fireGridSelectionChanged");
    }

    /**
     * 设置网格列头是否可见
     * 
     * @param columnHeaderVisible
     *            值
     */
    public void setColumnHeaderVisible(boolean columnHeaderVisible) {
        this.columnHeaderVisible = columnHeaderVisible;
        this.gridColumnHeader.setVisible(columnHeaderVisible);
    }

    /**
     * @return 列头是否可见
     */
    public boolean isColumnHeaderVisible() {
        return columnHeaderVisible;
    }

    /**
     * 设置网格行头是否可见
     * 
     * @param rowHeaderVisible
     *            设置值
     */
    public void setRowHeaderVisible(boolean rowHeaderVisible) {
        this.rowHeaderVisible = rowHeaderVisible;
        this.gridRowHeader.setVisible(columnHeaderVisible);
    }

    /**
     * @return 网格行头是否可见
     */
    public boolean isRowHeaderVisible() {
        return rowHeaderVisible;
    }

    /**
     * @return 获取列头
     */
    public GridColumnHeader getGridColumnHeader() {
        return this.gridColumnHeader;
    }

    /**
     * @return 获取行头
     */
    public GridRowHeader getGridRowHeader() {
        return this.gridRowHeader;
    }

    /**
     * 设置水平开始列数
     * 
     * @param horiBeginValue
     *            值
     */
    public void setHoriBeginValue(int horiBeginValue) {
        this.horiBeginValue = horiBeginValue;

        this.refresh();
    }

    /**
     * 
     * @return 水平开始列数(0 based)
     */
    public int getHoriBeginValue() {
        return horiBeginValue;
    }

    /**
     * 设置水平显示列数
     * 
     * @param horiValueExtend
     *            值
     */
    public void setHoriValueExtend(int horiValueExtend) {
        this.horiValueExtend = horiValueExtend;
    }

    /**
     * 
     * @return 水平显示列数
     */
    public int getHoriValueExtend() {
        return horiValueExtend;
    }

    /**
     * 设置垂直开始行数
     * 
     * @param vertBeginValue
     *            垂直开始行
     */
    public void setVertBeginValue(int vertBeginValue) {
        this.vertBeginValue = vertBeginValue;

        this.repaint();
    }

    /**
     * 
     * @return 垂直开始行(0 based)
     */
    public int getVertBeginValue() {
        return vertBeginValue;
    }

    /**
     * 设置垂直显示行数
     * 
     * @param vertValueExtend
     *            值
     */
    public void setVertValueExtend(int vertValueExtend) {
        this.vertValueExtend = vertValueExtend;
    }

    /**
     * 
     * @return 垂直显示行数
     */
    public int getVertValueExtend() {
        return vertValueExtend;
    }

    /**
     * @return 表格选择模型
     */
    public GridSelection getGridSelection() {
        return gridSelection;
    }

    /**
     * @return 获取行数
     */
    public int getRowCount() {
        return this.reportModel.getRowCount();
    }

    /**
     * 获取可处理的最大行
     * 
     * @return 可处理的最大行
     */
    public int getMaxRowCount() {
        return this.isShowActualColumnRow() ? this.getRowCount() : Integer.MAX_VALUE;
    }

    /**
     * @return 获取列数
     */
    public int getColumnCount() {
        return this.reportModel.getColumnCount();
    }

    /**
     * 获取可处理的最大列
     * 
     * @return 可处理的最大列
     */
    public int getMaxColumnCount() {
        return this.isShowActualColumnRow() ? this.getColumnCount() : Integer.MAX_VALUE;
    }

    /**
     * @return the verScrollBar
     */
    public DynamicScrollBar getVerScrollBar() {
        return verScrollBar;
    }

    public DynamicScrollBar getHorScrollBar() {
        return horScrollBar;
    }

    /**
     * 绘制单元格：自动判断是否要绘制
     * 
     * @param g2
     *            图形对象
     * @param column
     *            列
     * @param row
     *            行
     */
    public void paintCell(Graphics2D g2, int column, int row) {
        paintCell(g2, column, row, grid.getGridLineColor());
    }

    /**
     * 绘制单元格：自动判断是否要绘制
     * 
     * @param g2
     *            图形对象
     * @param column
     *            列
     * @param row
     *            行
     * @param borderColor
     *            边框颜色
     */
    public void paintCell(Graphics2D g2, int column, int row, Color borderColor) {
        Cell cell = reportModel.getCell(column, row);

        if (cell == Cell.EMPTY_CELL) {
            return;
        }

        Rectangle rect = reportModel.getCellRectangle(this, cell);

        // 合并的单元格
        if (this.isShowGridLines() && ((cell.getColumnSpan() > 1) || (cell.getRowSpan() > 1))) {
            g2.setPaint(Color.WHITE);
            g2.fill(rect);
            g2.setColor(borderColor);
            g2.draw(rect);
        }

        PaintUtils.paintCellElement(g2, cell, rect);
    }

    /**
     * 绘制单元格元素类型标志
     * 
     * @param g2
     *            图形对象
     * @param column
     *            列
     * @param row
     *            行
     */
    public void paintCellElementFlag(Graphics2D g2, int column, int row) {
        // DefaultCell cell = reportModel.getCell(column, row);
        //
        // // if (cell.isMerged()) {
        // // return;
        // // }
        //
        // Rectangle rect = reportModel.getCellRectangle(column, row);
        //
        // PaintUtils.paintCellElementFlag(g2, cell, rect);
    }

    /**
     * 获取焦点
     */
    public void setFocus() {
        this.requestFocus();
    }

    /**
     * 获取当前活动单元格
     * 
     * @return 当前活动单元格
     */
    public Cell getActiveCell() {
        Selection sel = gridSelection.getEditSelection();
        if (sel != null) {
            Cell ci = this.reportModel.getCell(sel);

            return ci;
        }

        return null;
    }

    /**
     * 返回当前编辑单元格Style
     * 
     * @return 当前编辑单元格Style
     */
    public Style getActiveCellStyle() {
        Cell cell = this.getActiveCell();

        if (cell == null) {
            return Style.DEFAULT_STYLE;
        } else {
            return cell.getStyle();
        }
    }

    /**
     * 合并单元格
     * 
     * @param columnFrom
     *            开始列
     * @param rowFrom
     *            开始行
     * @param columnSpan
     *            列跨度
     * @param rowSpan
     *            行跨度
     */
    public void mergeCell(int columnFrom, int rowFrom, int columnSpan, int rowSpan) {
        if (getGridSelection().getCellSelectionCount() > 1) {
            return;
        }

        this.reportModel.mergeCell(columnFrom, rowFrom, columnSpan, rowSpan);
        getGridSelection().setEditBounds(columnFrom, rowFrom, columnSpan, rowSpan);

        updateUI();
    }

    /**
     * 合并单元格
     * 
     * @param rect
     *            矩形区域
     */
    public void mergeCell(Selection selection) {
        this.mergeCell(selection.getColumn(), selection.getRow(), selection.getColumSpan(), selection.getRowSpan());
    }

    /**
     * 合并选择的单元格
     * 
     * @return
     */
    public void mergeCell() {
        this.mergeCell(this.getGridSelection().getLastCellSelection());
    }

    /**
     * 拆散单元格
     * 
     * @param columnFrom
     *            开始列
     * @param rowFrom
     *            开始行
     * @param columnSpan
     *            列跨度
     * @param rowSpan
     *            行跨度
     */
    public void unmergeCell(int columnFrom, int rowFrom, int columnSpan, int rowSpan) {
        this.reportModel.unmergeCell(columnFrom, rowFrom, columnSpan, rowSpan);
        this.getGridSelection().setEditBounds(columnFrom, rowFrom, 1, 1);

        updateUI();
    }

    /**
     * 拆散单元格
     * 
     * @param rect
     *            区域
     */
    public void unmergeCell(Selection selection) {
        this.unmergeCell(selection.getColumn(), selection.getRow(), selection.getColumSpan(), selection.getRowSpan());
    }

    /**
     * 取消单元格合并
     * 
     * @return
     */
    public void unmergeCell() {
        this.unmergeCell(getGridSelection().getLastCellSelection());
    }

    /**
     * 获取所有选择的单元格列表,该方法会对所有的选择的单元格进行处理，如果单元格还不包括cell，则创建Cell,被合并的单元格不要处理
     * 
     * @return 选择的单元格列表
     */
    public List<Cell> getSelectedCells() {
        List<Cell> result = new ArrayList<Cell>();
        for (Selection rect : getGridSelection().getCellSelectionList()) {
            for (int i = 0, clen = rect.getColumSpan(); i < clen; i++) {
                int col = rect.getColumn() + i;
                for (int j = 0, rlen = rect.getRowSpan(); j < rlen; j++) {
                    int row = rect.getRow() + j;
                    Cell cell = this.reportModel.getCell(col, row);

                    if (cell == Cell.EMPTY_CELL) {
                        // 必须没有被合并
                        if (this.reportModel.getMergedToCell(col, row) == Cell.EMPTY_CELL) {
                            cell = new Cell(col, row);
                            this.reportModel.addCell(cell);

                            result.add(cell);
                        }
                    } else {
                        result.add(cell);
                    }
                }
            }
        }

        return result;
    }

    /**
     * 获取网格
     * 
     * @return 网格
     */
    public Grid getGrid() {
        return this.grid;
    }

    /**
     * @return 最后一个选择集
     */
    public Selection getLastCellSelection() {
        return this.getGridSelection().getLastCellSelection();
    }

    /**
     * 工作薄刷新，调用此函数更新组件
     */
    public void refresh() {
        this.repaint();
    }

    /**
     * 设置单元格对象值
     * 
     * @param column
     *            列
     * @param row
     *            行
     * @param value
     *            值
     */
    public void setCellValue(int column, int row, Object value) {
        this.reportModel.setCellValue(column, row, value);
    }

    /**
     * 设置Grid菜单
     * 
     * @param gridActionMenu
     *            Grid菜单
     */
    public void setGridActionMenu(JPopupMenu gridActionMenu) {
        this.grid.setGridActionMenu(gridActionMenu);
    }

    /**
     * 设置是否显示固定行列
     * 
     * @param showActualColumnRow 设置值
     */
    public void setShowActualColumnRow(boolean showActualColumnRow) {
        this.showActualColumnRow = showActualColumnRow;
    }

    /**
     * 是否显示固定行列
     * 
     * @return 显示固定行列
     */
    public boolean isShowActualColumnRow() {
        return showActualColumnRow;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        // String propertyName = evt.getPropertyName();
        //
        // if ("ColumnCount".equals(propertyName) ||
        // "RowCount".equals(propertyName)) {
        // this.refresh();
        // }
    }
}
